/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Global Trust Authority is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

use std::future::Future;
use std::pin::Pin;

use crate::{
    entities::{
        attest_request::{Evidence, Measurement},
        token::{token_trait::{Token, AttesterResult}, PolicyInfo},
    },
    error::attestation_error::AttestationError,
};

/// Attestation context containing all data needed during the verification process
pub struct AttestationContext {
    pub measurement: Measurement,
    pub evidence: Evidence,
    pub user_id: String,
    pub token_instance: Box<dyn Token>,
    pub nonce_bytes: Option<Vec<u8>>,
    pub aggregate_nonce_bytes: Option<Vec<u8>>,
    pub verify_evidence: Option<serde_json::Value>,
    pub raw_evidence: Option<serde_json::Value>,
    pub custom_verify_results: Vec<bool>,
    pub custom_evaluate_results: Vec<PolicyInfo>,
    pub evidence_token_response: Option<AttesterResult>,
}

impl AttestationContext {
    pub fn new(measurement: Measurement, evidence: Evidence, user_id: String, token_instance: Box<dyn Token>) -> Self {
        Self {
            measurement,
            evidence,
            user_id,
            token_instance,
            nonce_bytes: None,
            aggregate_nonce_bytes: None,
            verify_evidence: None,
            raw_evidence: None,
            custom_verify_results: Vec::new(),
            custom_evaluate_results: Vec::new(),
            evidence_token_response: None,
        }
    }
}

/// Trait for handling attestation steps in a chain of responsibility pattern
pub trait AttestationHandler: Send + Sync {
    /// Handle the current step of attestation
    fn handle<'a>(&'a self, context: &'a mut AttestationContext) -> Pin<Box<dyn Future<Output = Result<(), AttestationError>> + Send + 'a>>;
    
    /// Set the next handler in the chain
    fn set_next(&mut self, next: Box<dyn AttestationHandler>);
    
    /// Execute this handler and continue to the next one if present
    fn execute<'a>(&'a self, context: &'a mut AttestationContext) -> Pin<Box<dyn Future<Output = Result<(), AttestationError>> + Send + 'a>> {
        Box::pin(async move {
            self.handle(context).await?;
            if let Some(next) = self.get_next() {
                next.execute(context).await?;
            }
            Ok(())
        })
    }
    
    /// Get the name of this handler for debugging
    fn name(&self) -> &'static str;
    
    /// Get the next handler in the chain
    fn get_next(&self) -> Option<&dyn AttestationHandler>;
}